// import * as Cesium from 'cesium';
import useMapStore from '@/stores/storeMap.js';
import { QIN_LING_SHAN_MA } from '../map-geoJson/秦岭山脉.js';
import { getTDTkey } from './common-cesium-info.js';
import { addCircleScan, addRadarScan } from './map-material.js';

// * 保存地图实例
export let viewer = null;

const Cesium = window.Cesium;

/**
 * 相机绕点飞行执行函数，变量用于监听和取消监听
 */
let Exection = null;

let time = null;

const mapStore = useMapStore();

/**
 * 地图初始化
 * @returns {Cesium.Viewer}
 */
export const CESIUM_MAP_INIT = async (box) => {
  viewer = new Cesium.Viewer(box, {
    animation: false, //是否创建动画小器件，左下角仪表

    baseLayerPicker: false, //是否显示图层选择器，右上角图层选择按钮

    fullscreenButton: false, //是否显示全屏按钮，右下角全屏选择按钮

    geocoder: false, //是否显示geocoder小器件，右上角查询按钮

    navigationInstructionsInitiallyVisible: false, // 不显示提示

    homeButton: false, //是否显示Home按钮，右上角home按钮

    skyAtmosphere: false, // 关闭大气

    sceneMode: Cesium.SceneMode.SCENE3D, //初始场景模式

    sceneModePicker: false, //是否显示3D/2D选择器，右上角按钮

    navigationHelpButton: false, //是否显示右上角的帮助按钮

    selectionIndicator: false, //是否显示选取指示器组件

    timeline: false, //是否显示时间轴

    infoBox: false, //是否显示信息框

    scene3DOnly: true, //如果设置为true，则所有几何图形以3D模式绘制以节约GPU资源

    orderIndependentTranslucency: true, //是否启用无序透明

    shadows: true, // 开启阴影

    shouldAnimate: true, // 开启动画

    contextOptions: { webgl: { alpha: true } },

    skyBox: new Cesium.SkyBox({ show: false }),

    //!这里有时候会出现403错误 这里用了默认地形
    terrainProvider: await Cesium.createWorldTerrainAsync({
      requestWaterMask: true,
      requestVertexNormals: true,
      // heightmapTerrainQuality: 2,
    }),
  });

  viewer.scene.sun.show = false;

  viewer.scene.moon.show = false;

  viewer.scene.skyBox.show = false;

  // 开启深度检测
  viewer.scene.globe.depthTestAgainstTerrain = true;

  viewer.scene.backgroundColor = new Cesium.Color(0.0, 0.0, 0.0, 1);

  viewer._cesiumWidget._creditContainer.style.display = 'none';

  // * 调整鼠标习惯
  viewer.scene.screenSpaceCameraController.zoomEventTypes = [
    Cesium.CameraEventType.WHEEL,
    Cesium.CameraEventType.PINCH,
  ];
  viewer.scene.screenSpaceCameraController.tiltEventTypes = [
    Cesium.CameraEventType.PINCH,
    Cesium.CameraEventType.RIGHT_DRAG,
    {
      eventType: Cesium.CameraEventType.RIGHT_DRAG,
      modifier: Cesium.KeyboardEventModifier.CTRL,
    },
  ];
  // 旋转挂载
  MAP_AUTO_ROTATE();

  // 获取鼠标点击坐标
  // GET_MAP_POINT();

  // 蒙层
  // INVERT_MASK();

  viewer.imageryLayers.addImageryProvider(TDT_DX);
  viewer.imageryLayers.addImageryProvider(ARCGIS);
  viewer.imageryLayers.addImageryProvider(TDT_ZJ);
  viewer.imageryLayers.addImageryProvider(TDT_SL);
  viewer.imageryLayers.addImageryProvider(TDT_YX);
  window.map3d = viewer;

  // viewer.camera.setView({
  //   destination: Cesium.Cartesian3.fromDegrees(116.36485552299206, 39.99754814959118, 5000.0),
  // });

  // new CircleScanSystem(viewer, {
  //   type: 'Circle',
  //   lon: '116.34485552299206',
  //   lat: '39.99754814959118',
  // });
  // new CircleScanSystem(viewer, {
  //   type: 'Radar',
  //   lon: '116.37986552299206',
  //   lat: '39.99754814959118',
  // });
  // new CircleScanSystem(viewer, {
  //   type: 'Radar',
  //   lon: '116.34485552299206',
  //   lat: '39.97954814959118',
  // });

  return viewer;
};

/**
 * 获取viewer
 * @returns {Cesium.Viewer}
 */
export function MAP_INIT_3d() {
  return viewer;
}

/**
 * 添加图层
 * @param {Cesium.ImageryLayer} layer
 */

export const TDT_SL = new Cesium.WebMapTileServiceImageryProvider({
  url: `http://{s}.tianditu.gov.cn/vec_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=vec&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=${getTDTkey()}`,
  layer: 'vec',
  style: 'default',
  format: 'tiles',
  tileMatrixSetID: 'w',
  subdomains: ['t0', 't1', 't2', 't3', 't4', 't5', 't6', 't7'],
  credit: new Cesium.Credit('天地图矢量'),
  maximumLevel: 18,
});

export const TDT_YX = new Cesium.WebMapTileServiceImageryProvider({
  url: `http://{s}.tianditu.gov.cn/img_w/wmts?tk=${getTDTkey()}`,
  format: 'tiles',
  layer: 'img',
  style: 'default',
  tileMatrixSetID: 'w',
  maximumLevel: 18,
  subdomains: ['t0', 't1', 't2', 't3', 't4', 't5', 't6', 't7'],
  credit: new Cesium.Credit('天地图影像'),
});

export const TDT_DX = new Cesium.WebMapTileServiceImageryProvider({
  url: `http://{s}.tianditu.gov.cn/ter_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=ter&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=${getTDTkey()}`,
  layer: '111',
  style: 'default',
  format: '111',
  tileMatrixSetID: '11',
  subdomains: ['t0', 't1', 't2', 't3', 't4', 't5', 't6', 't7'],
  credit: new Cesium.Credit('天地图地形'),
  maximumLevel: 18,
});

// 加载影像注记
export const TDT_ZJ = new Cesium.WebMapTileServiceImageryProvider({
  url: `http://{s}.tianditu.gov.cn/cia_w/wmts?tk=${getTDTkey()}`,
  layer: 'cia',
  style: 'default',
  tileMatrixSetID: 'w',
  format: 'tiles',
  subdomains: ['t0', 't1', 't2', 't3', 't4', 't5', 't6', 't7'],
  credit: new Cesium.Credit('天地注记'),
  maximumLevel: 18,
});

export const ARCGIS = new Cesium.WebMapTileServiceImageryProvider({
  url: 'https://services.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/WMTS',
  layer: 'World_Imagery',
  style: 'default',
  format: 'image/jpeg',
  tileMatrixSetID: 'GoogleMapsCompatible',
  maximumLevel: 19,
  credit: new Cesium.Credit('ARCGIS'),
});

/**
 * 切换底图
 * @param {type} type - 底图类型 'TDT_SL' | 'TDT_YX' | 'TDT_DX' | 'TDT_ZJ' | 'ARCGIS' | 'REMOVE'
 */
export const TOGGLE_BASE_MAP = (type, VIEWER = viewer) => {
  switch (type) {
    case 'TDT_YX':
      VIEWER.imageryLayers.get(1).show = false;
      VIEWER.imageryLayers.get(2).show = false;
      VIEWER.imageryLayers.get(3).show = false;
      VIEWER.imageryLayers.get(4).show = false;
      VIEWER.imageryLayers.get(5).show = true;
      break;

    case 'TDT_SL':
      VIEWER.imageryLayers.get(1).show = false;
      VIEWER.imageryLayers.get(2).show = false;
      VIEWER.imageryLayers.get(3).show = false;
      VIEWER.imageryLayers.get(4).show = true;
      VIEWER.imageryLayers.get(5).show = false;
      break;

    case 'ARCGIS':
      VIEWER.imageryLayers.get(1).show = false;
      VIEWER.imageryLayers.get(2).show = true;
      VIEWER.imageryLayers.get(3).show = false;
      VIEWER.imageryLayers.get(4).show = false;
      VIEWER.imageryLayers.get(5).show = false;
      break;

    case 'TDT_ZJ':
      VIEWER.imageryLayers.get(1).show = false;
      VIEWER.imageryLayers.get(2).show = false;
      VIEWER.imageryLayers.get(3).show = true;
      VIEWER.imageryLayers.get(4).show = false;
      VIEWER.imageryLayers.get(5).show = false;

      break;

    case 'TDT_DX':
      VIEWER.imageryLayers.get(1).show = true;
      VIEWER.imageryLayers.get(2).show = false;
      VIEWER.imageryLayers.get(3).show = false;
      VIEWER.imageryLayers.get(4).show = false;
      VIEWER.imageryLayers.get(5).show = false;
      break;

    default:
      break;
  }
};

/**
 * 二三维场景切换
 */

export function SET_VIEW_TYPE(viewType) {
  let scene = viewer.scene;
  let camera = viewer.camera;

  switch (viewType) {
    case '3d':
      scene.morphTo2D(1.0);

      // 定位到西安的经纬度，海拔高度为 1000 米
      camera.flyTo({
        destination: Cesium.Cartesian3.fromDegrees(108.940174, 34.341568, 1000),
        duration: 2, // 设置平滑过渡时间为 2 秒

        orientation: {
          heading: Cesium.Math.toRadians(348.4202942851978),
          pitch: Cesium.Math.toRadians(-89.74026687972041),
          roll: Cesium.Math.toRadians(0),
        },
        complete: function callback() {},
      });

      mapStore.CHANGE_MODE('2d');

      break;

    case '2d':
      scene.morphTo3D(1.0);

      setTimeout(() => {
        MAP_SET_VIEW();
      }, 10);

      mapStore.CHANGE_MODE('3d');

      break;

    default:
      break;
  }
}

/**
 * 地球自动旋转函数
 * !当点击地图时停止旋转，双击地图开始旋转
 */
export function MAP_AUTO_ROTATE() {
  let map = viewer;

  map.clock.multiplier = 60; //速度
  map.clock.shouldAnimate = false;

  let previousTime = map.clock.currentTime.secondsOfDay;

  function onTickCallback() {
    let spinRate = 1;
    let currentTime = map.clock.currentTime.secondsOfDay;
    let delta = (currentTime - previousTime) / 1000;

    previousTime = currentTime;
    map.scene.camera.rotate(Cesium.Cartesian3.UNIT_Z, -spinRate * delta);
  }

  map.clock.onTick.addEventListener(onTickCallback);

  // ! 监听点击事件，当点击地图时停止旋转，双击地图开始旋转
  const handler = new Cesium.ScreenSpaceEventHandler(map.scene.canvas);

  handler.setInputAction(() => {
    map.clock.shouldAnimate = false;
    map.clock.onTick.removeEventListener(onTickCallback);
  }, Cesium.ScreenSpaceEventType.LEFT_DOWN);

  handler.setInputAction(() => {
    map.clock.shouldAnimate = true;
    map.clock.onTick.addEventListener(onTickCallback);
  }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
}

/**
 * 初始化地图视角
 */
export function FLY_TO_HOME() {
  // 宇宙视角
  viewer.camera.flyTo({
    destination: Cesium.Cartesian3.fromDegrees(103.84, 31.15, 16000000),
    orientation: {
      heading: Cesium.Math.toRadians(348.4202942851978),
      pitch: Cesium.Math.toRadians(-89.74026687972041),
      roll: Cesium.Math.toRadians(0),
    },
    complete: function callback() {},
  });

  MAP_START_ROTATE();

  // !相机360度环绕固定点旋转
  // setTimeout(() => {
  //   viewer.camera.flyTo({
  //     destination: Cesium.Cartesian3.fromDegrees(110.76798078566588, 34.82389915971464, 10000),
  //     complete: function callback() {
  //       ROTATE_CAMERA({ lon: 110.76798078566588, lat: 34.82389915971464, pitch: -35, height: 10000, time: 30 });
  //     },
  //   });
  // }, 3000);
}

/**
 * 调整视角
 */
export function MAP_SET_VIEW() {
  viewer &&
    viewer.camera.flyTo({
      destination: Cesium.Cartesian3.fromDegrees(103.84, 31.15, 16000000),
    });
}

/**
 * 开始自转
 */
export function MAP_START_ROTATE() {
  viewer.clock.shouldAnimate = true;
}

/**
 * 停止自转
 */
export function MAP_STOP_ROTATE() {
  if (!viewer) return;
  viewer.clock.shouldAnimate = false;
}

/**
 * 获取鼠标点击坐标
 */
export function GET_MAP_POINT() {
  let map = viewer;

  const handler = new Cesium.ScreenSpaceEventHandler(map.scene.canvas);
  // 添加了tip此处为点击旋转实体触发
  const tooltipCesium = new TooltipDivs({ frameDiv: map.cesiumWidget.container });
  // 获取场景
  const scene = map.scene;
  const ellipsoid = scene.globe.ellipsoid;

  handler.setInputAction(function (movement) {
    // 获取点击的屏幕坐标
    const clickPosition = movement.position;

    console.info(clickPosition, 'clickPosition');

    var cartesian = map.camera.pickEllipsoid(clickPosition, map.scene.globe.ellipsoid);

    if (cartesian) {
      var cartographic = Cesium.Cartographic.fromCartesian(cartesian);
      var longitude = Cesium.Math.toDegrees(cartographic.longitude);
      var latitude = Cesium.Math.toDegrees(cartographic.latitude);
      var height = cartographic.height;

      console.info('Clicked at: ', longitude, ',', latitude, height);
    }

    // -------------------------------------------------------------------------------
    let pickedObject = scene.pick(clickPosition);
    // 将屏幕坐标转换为地理坐标
    const pickRay = scene.camera.getPickRay(clickPosition);
    const intersection = scene.globe.pick(pickRay, scene);

    tooltipCesium.setVisible(false);

    if (Cesium.defined(pickedObject)) {
      // const position = pickedObject.id.position.getValue(Cesium.JulianDate.now());

      // 点击了实体
      cartesian = map.camera.pickEllipsoid(clickPosition, ellipsoid);

      if (intersection) {
        // 获取点击处的地理坐标
        const position = Cesium.Ellipsoid.WGS84.cartesianToCartographic(intersection);

        // 在此处执行点击实体的操作，可以根据实际需要来处理点击事件
        // 例如根据地理坐标查询实体等等
        let point = Cesium.Cartesian3.fromDegrees(
          Cesium.Math.toDegrees(position.longitude),
          Cesium.Math.toDegrees(position.latitude),
          Cesium.Math.toDegrees(position.height),
        );

        console.info('点击位置：', position, point);

        // 将 Cartesian3 坐标转换为屏幕坐标
        const screenPosition = new Cesium.Cartesian2();

        if (Cesium.SceneTransforms.wgs84ToWindowCoordinates(scene, point, screenPosition)) {
          // screenPosition.x 和 screenPosition.y 分别是点在屏幕上的 x 和 y 坐标
          console.info('屏幕坐标：', screenPosition.x, screenPosition.y);
        } else {
          console.info('点不在视野范围内。');
        }
      }
    }
  }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
}

/**
 * 销毁 Viewer 实例
 */
export const DESTROY_CESIUM_VIEWER = () => {
  if (viewer) {
    viewer.destroy(); // 销毁 Cesium Viewer 实例
    viewer = null; // 清空全局变量
  }
};

/**
 * 移除指定图层
 * @param {Cesium.ImageryLayer} layer - 需要移除的图层实例
 */
export const REMOVE_MAP_LAYER = (layer) => {
  if (viewer && layer) {
    viewer.imageryLayers.remove(layer, true); // true 表示销毁图层
  }
};

/**
 * 移除所有图层
 */
export const REMOVE_ALL_LAYERS = () => {
  if (viewer) {
    viewer.imageryLayers.removeAll(true); // true 表示销毁所有图层
  }
};

/**
 * 移除所有
 */
export const REMOVE_ALL_ENTITIES = () => {
  if (viewer) {
    viewer.entities.removeAll(true);
  }
};

/**
 * 相机360度环绕固定点旋转
 * @param {{lon:number,lat:number,time:number,pitch:number,height:number,cb?:()=>}} options 相关配置
 */
export const ROTATE_CAMERA = (options) => {
  let map = viewer;
  var position = Cesium.Cartesian3.fromDegrees(options.lon, options.lat, 0.0);
  // 相机看点的角度，如果大于0那么则是从地底往上看，所以要为负值。
  var pitch = Cesium.Math.toRadians(options.pitch);
  // 给定飞行一周所需时间，比如30s, 那么每秒转动度数
  var angle = 360 / options.time;
  // 给定相机距离点多少距离飞行
  var distance = options.height;
  var startTime = Cesium.JulianDate.fromDate(new Date());

  var stopTime = Cesium.JulianDate.addSeconds(startTime, options.time, new Cesium.JulianDate());

  map.clock.startTime = startTime.clone(); // 开始时间
  map.clock.stopTime = stopTime.clone(); // 结束时间
  map.clock.currentTime = startTime.clone(); // 当前时间
  map.clock.clockRange = Cesium.ClockRange.CLAMPED; // 行为方式
  map.clock.clockStep = Cesium.ClockStep.SYSTEM_CLOCK; // 时钟设置为当前系统时间; 忽略所有其他设置。

  // 相机的当前heading
  var initialHeading = map.camera.heading;

  Exection = function TimeExecution() {
    // 当前已经过去的时间，单位s
    var delTime = Cesium.JulianDate.secondsDifference(map.clock.currentTime, map.clock.startTime);
    // 根据过去的时间，计算偏航角的变化
    var heading = Cesium.Math.toRadians(delTime * angle) + initialHeading;

    map.camera.lookAt(position, new Cesium.HeadingPitchRange(heading, pitch, distance));
  };

  map.clock.onTick.addEventListener(Exection);

  //清除定时器
  clearTimeout(time);
  //生成定时器
  time = setTimeout(() => {
    map.clock.onTick.removeEventListener(onTickCallback);
    map.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
    map.clock.onTick.removeEventListener(Exection);
    Exection = null;
    options.cb && options.cb();
  }, options.time * 1000);
};

/**
 * 关闭绕点动画行为
 * @param {{lon:number,lat:number,time:number,pitch:number,height:number,cb?:()=>}} options 相关配置
 */
export const CLEAR_ROTATE_CAMERA = () => {
  let map = viewer;

  //清除定时器
  clearTimeout(time);
  onTickCallback && map.clock.onTick.removeEventListener(onTickCallback);
  map.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
  Exection && map.clock.onTick.removeEventListener(Exection);
  Exection = null;
};

/**
 * 标记回调函数
 */
function onTickCallback() {
  let map = viewer;

  let previousTime = map.clock.currentTime.secondsOfDay;
  let spinRate = 1;
  let currentTime = map.clock.currentTime.secondsOfDay;
  let delta = (currentTime - previousTime) / 1000;

  previousTime = currentTime;
  map.scene.camera.rotate(Cesium.Cartesian3.UNIT_Z, -spinRate * delta);
}

/**
 *
 *
 * @export
 * @class TooltipDivs
 */
export class TooltipDivs {
  constructor({ frameDiv, id }) {
    this.isInit = false;
    this._div = undefined;
    this._title = undefined;
    this.id = id ?? Date.now();
    this.initTool(frameDiv);
  }
  initTool(frameDiv) {
    if (!frameDiv) throw new Error('frameDiv 是必须的！');

    if (this.isInit) {
      return this;
    }

    var div = document.createElement('div');

    div.className = 'tooltipdiv right'; //
    div.id = this.id;

    var arrow = document.createElement('div');

    arrow.className = 'tooltipdiv-arrow';

    div.appendChild(arrow);

    var title = document.createElement('div');

    title.className = 'tooltipdiv-inner';

    div.appendChild(title);

    this._div = div;

    this._title = title;

    frameDiv.appendChild(div);

    this.isInit = true;

    return this;
  }

  setVisible(visible) {
    if (!this.isInit) {
      return;
    }

    this._div.style.display = visible ? 'block' : 'none';
  }

  showAt(position, message) {
    if (!this.isInit) {
      return;
    }

    if (position && message) {
      this.setVisible(true);

      this._title.innerHTML = message;

      this._div.style.left = position.x + 10 + 'px';

      this._div.style.top = position.y - this._div.clientHeight / 2 + 'px';
    }
  }

  remove() {
    this._div.remove();
  }
}

/***
 * @category  场景
 * @classdesc 场景特效-扩散及扫描特效
 * @param {Object} options - 参数。
 * @param {String} options.type - 扫描类型  Circle:圆形扩大扫描圈 Radar:区域雷达扫描。
 * @param {Boolean} options.lon - 经度 。
 * @param {Boolean} options.lat -纬度 。
 * @param {String} options.radius - 扫描半径 （默认 1000).
 * @param {String} options.scanColor - 颜色  注意颜色必须是 new Cesium.Color(1.0, 0.0, 0.0, 1);rgba形式的‘red’和‘#fff’都不行（默认  new Cesium.Color(1.0, 0.0, 0.0, 1).
 * @param {String} options.interval - 时间 （默认 3000）.
 */
export class CircleScanSystem {
  constructor(viewer, options) {
    this.viewer = viewer;

    var data = {
      radius: options.radius || '100',
      scanColor: new Cesium.Color(1.0, 0.0, 0.0, 1),
      interval: '3000',
    };

    this.data = Object.assign(data, options);
    this.primitives = null;

    if (options.type == 'Circle') {
      this.primitives = addCircleScan(this.viewer, this.data);
    } else if (options.type == 'Radar') {
      this.primitives = addRadarScan(this.viewer, this.data);
    }
  }
  /**
   *清除
   * */
  remove() {
    this.viewer.scene.postProcessStages.remove(this.primitives);
  }
}

/**
 * 反选遮罩蒙层
 */
export function INVERT_MASK() {
  viewer.scene.debugShowFramesPerSecond = true;

  const maskpointArray = [];

  for (let i = 0; i < QIN_LING_SHAN_MA.features[0].geometry.coordinates[0].length; i++) {
    maskpointArray.push(QIN_LING_SHAN_MA.features[0].geometry.coordinates[0][i][0]);
    maskpointArray.push(QIN_LING_SHAN_MA.features[0].geometry.coordinates[0][i][1]);
  }

  var maskspoint = Cesium.Cartesian3.fromDegreesArray(maskpointArray);
  const area = new Cesium.Entity({
    id: 1,
    polygon: {
      hierarchy: {
        positions: Cesium.Cartesian3.fromDegreesArray([100, 0, 100, 89, 150, 89, 150, 0]), //外部区域
        holes: [
          {
            positions: maskspoint, //挖空区域
          },
        ],
      },
      material: Cesium.Color.BLACK.withAlpha(0.6), //外部颜色
    },
  });
  const line = new Cesium.Entity({
    id: 2,
    polyline: {
      positions: maskspoint,
      width: 4, //边界线宽
      material: Cesium.Color.fromCssColorString('#6dcdeb'), //边界线颜色
      clampToGround: true, // 贴地属性
    },
  });

  viewer.entities.add(area);
  viewer.entities.add(line);
  viewer.flyTo(line, { duration: 3 });
}

/***
 * 测量距离工具
 * @param {Object} options - 参数。
 * @param {String} options.type - 类型  Line:直线距离 Label:标签距离。
 */
let clampToGround = true;

export const MeasureMapTool = (text) => {
  let measure = new Cesium.Measure(viewer);

  if (text) {
    switch (text) {
      case '不贴地':
        clampToGround = false;
        break;

      case '空间距离':
        measure.drawLineMeasureGraphics({ clampToGround: clampToGround, callback: () => {} });
        break;

      case '空间面积':
        measure.drawAreaMeasureGraphics({ clampToGround: clampToGround, callback: () => {} });
        break;

      case '三角量测':
        measure.drawTrianglesMeasureGraphics({ callback: () => {} });
        break;

      case '清除量测':
        measure._drawLayer.entities.removeAll();
        break;

      case '加载模型':
        // loadModel();
        break;
    }
  }
};
